Return to start page

Core/Environment/Library Unit.j

Code

		
1			/// Provides several functions for unit handling.
2 /// @author Tamino Dauth
3 library ALibraryCoreEnvironmentUnit requires ALibraryCoreMathsReal
4
5 /**
6 * Adds or removes the move ability to unit @param usedUnit.
7 * @author Tamino Dauth
8 * @param usedUnit The unit which the ability is added to.
9 * @param movable If this value is true the ability will be added to unit @param usedUnit, otherwise it will be removed.
10 */
11 function MakeUnitMovable takes unit usedUnit, boolean movable returns nothing
12 if (movable) then
13 call UnitAddAbility(usedUnit, 'Amov')
14 else
15 call UnitRemoveAbility(usedUnit, 'Amov')
16 endif
17 endfunction
18
19 /**
20 * Adds or removes the attack ability to unit @param usedUnit.
21 * @author Tamino Dauth
22 * @param usedUnit The unit which the ability is added to.
23 * @param attackable If this value is true the ability will be added to unit @param usedUnit, otherwise it will be removed.
24 */
25 function MakeUnitAttackable takes unit usedUnit, boolean attackable returns nothing
26 if (attackable) then
27 call UnitAddAbility(usedUnit, 'Aatk')
28 else
29 call UnitRemoveAbility(usedUnit, 'Aatk')
30 endif
31 endfunction
32
33 /// @todo Doesn't work.
34 /// @author Tamino Dauth
35 /// @return Returns true if unit @param usedUnit is invulnerable.
36 function IsUnitInvulnerable takes unit usedUnit returns boolean
37 return (GetUnitAbilityLevel(usedUnit, 'Bvul') > 0)
38 endfunction
39
40 /**
41 * @todo Function does not support all alliance states (only bj_ALLIANCE_NEUTRAL, bj_ALLIANCE_ALLIED and bj_ALLIANCE_UNALLIED).
42 * @author Tamino Dauth
43 * @return Returns the alliance state of the two unit's owners.
44 */
45 function GetUnitAllianceStateToUnit takes unit usedUnit, unit otherUnit returns integer
46 local player usedUnitOwner = GetOwningPlayer(usedUnit)
47 local player otherUnitOwner = GetOwningPlayer(otherUnit)
48 local integer allianceState = -1
49 if (IsPlayerAlly(usedUnitOwner, otherUnitOwner)) then
50 if (GetPlayerAlliance(usedUnitOwner, otherUnitOwner, ALLIANCE_PASSIVE)) then
51 set allianceState = bj_ALLIANCE_NEUTRAL
52 else
53 set allianceState = bj_ALLIANCE_ALLIED
54 endif
55 else
56 set allianceState = bj_ALLIANCE_UNALLIED
57 endif
58 set usedUnitOwner = null
59 set otherUnitOwner = null
60 return allianceState
61 endfunction
62
63 /**
64 * @author Anitarf
65 * @author Tamino Dauth (removed leak)
66 * @source http://www.wc3c.net/
67 */
68 function IsUnitSpellResistant takes unit u returns boolean
69 local player owner = GetOwningPlayer(u)
70 local boolean result = IsUnitType(u, UNIT_TYPE_HERO) or IsUnitType(u, UNIT_TYPE_RESISTANT) or (GetPlayerId(owner) >= PLAYER_NEUTRAL_AGGRESSIVE and GetUnitLevel(u) >= 6) //the level at which creeps gain spell resistance
71 set owner = null
72 return result
73 endfunction
74
75 /// @author Anitarf
76 /// @source http://www.wc3c.net/
77 function IsUnitSpellImmune takes unit u returns boolean
78 return IsUnitType(u, UNIT_TYPE_MAGIC_IMMUNE)
79 endfunction
80
81 /**
82 * Other functions available for use are GetFullDamage and GetReducedDamage.
83 * GetFullDamage, when passed the actual damage a unit takes (In most cases,
84 * GetEventDamage from EVENT_UNIT_DAMAGED event callbacks) and a unit's armor,
85 * it will return how much damage was dealt before armor reduction. Similarly,
86 * GetReducedDamage, when given the base damage and armor, will return how much
87 * damage will be dealt after armor is considered. These functions DO NOT
88 * consider armor types in their calculations, so any further reductions or
89 * bonuses due to that will need to be considered BEFORE using these functions.
90 * I recommend using your damage detection system to modify and build your own
91 * armor types anyways.
92 *
93 * You can use the ObjectMerger call below in order to generate the ability for
94 * keeping units with maximum life lower than DAMAGE_TEST from dying when
95 * using GetUnitArmor on them. If you do not plan on editing the 'AIlz' ability
96 * in your map, you can keep the ObjectMerger call commented out and replace
97 * 'lif&' in the configuration constants with 'AIlz'. The 'AIlz' ability adds
98 * 50 max life, which is plenty for the script.
99 *
100 * Function Listing --
101 * function GetUnitArmor takes unit u returns real
102 * function GetReducedDamage takes real baseDamage, real armor returns real
103 * function GetFullDamage takes real damage, real armor returns real
104 */
105 globals
106 //Values that should be changed for your map
107 private constant real ARMOR_REDUCTION_MULTIPLIER = 0.06 /// @author Rising_Dusk
108 private constant integer LIFE_BONUS_SPELL_ID = 'lif&' /// @author Rising_Dusk
109 //Values that do not need to be changed
110 constant real ARMOR_INVULNERABLE = 917451.519 /// @author Rising_Dusk
111 private constant real DAMAGE_TEST = 16. /// @author Rising_Dusk
112 private constant real DAMAGE_LIFE = 30. /// @author Rising_Dusk
113 private constant real NATLOG_094 = -0.061875 /// @author Rising_Dusk
114 endglobals
115
116 ////! external ObjectMerger w3a AIlz lif& anam "GetUnitArmorLifeBonus" ansf "" Ilif 1 30 aite 0
117
118 /// @author Rising_Dusk
119 function GetUnitArmor takes unit u returns real
120 local real life = GetWidgetLife(u)
121 local real test = life
122 local real redc = 0.
123 local boolean enab = false
124 local trigger trig = GetTriggeringTrigger()
125 if (u != null and life >= 0.405) then
126 if (GetUnitState(u, UNIT_STATE_MAX_LIFE) <= DAMAGE_TEST) then
127 //Add max life to keep it alive
128 call UnitAddAbility(u, LIFE_BONUS_SPELL_ID)
129 endif
130 if (life <= DAMAGE_LIFE) then
131 //If under the threshold, heal it for the moment
132 call SetWidgetLife(u, DAMAGE_LIFE)
133 set test = DAMAGE_LIFE
134 endif
135 if (trig != null and IsTriggerEnabled(trig)) then
136 //Disable the trigger to prevent it registering with damage detection systems
137 call DisableTrigger(trig)
138 set enab = true
139 endif
140 call UnitDamageTarget(u, u, DAMAGE_TEST, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null)
141 set redc = (DAMAGE_TEST - test + GetWidgetLife(u)) / DAMAGE_TEST
142 if (enab) then
143 //Re-enable the trigger
144 call EnableTrigger(trig)
145 endif
146 //Remove the max life ability
147 call UnitRemoveAbility(u, LIFE_BONUS_SPELL_ID)
148 call SetWidgetLife(u, life)
149 set trig = null
150 if (redc >= 1.0) then
151 //Invulnerable
152 return ARMOR_INVULNERABLE
153 elseif (redc < 0.0) then
154 //Negative Armor
155 return -ALog(redc + 1.0, 20) / NATLOG_094
156 else
157 //Positive Armor
158 return redc / (ARMOR_REDUCTION_MULTIPLIER * (1.0 - redc))
159 endif
160 endif
161 set trig = null
162 return 0.0
163 endfunction
164
165 /// @author Rising_Dusk
166 function GetReducedDamage takes real baseDamage, real armor returns real
167 if (armor >= 0.0) then
168 return baseDamage * (1.0 - ((armor * ARMOR_REDUCTION_MULTIPLIER) / (1.0 + ARMOR_REDUCTION_MULTIPLIER * armor)))
169 endif
170 return baseDamage * (2.0 -Pow(0.94, -armor))
171 endfunction
172
173 /// @author Rising_Dusk
174 function GetFullDamage takes real damage, real armor returns real
175 if (armor >= 0.0) then
176 return damage / (1.0 -((armor * ARMOR_REDUCTION_MULTIPLIER) / (1.0 + ARMOR_REDUCTION_MULTIPLIER * armor)))
177 endif
178 return damage / (2.0 -Pow(0.94, -armor))
179 endfunction
180
181 endlibrary